#!/usr/bin/python
# -*- coding: utf-8 -*-
import os.path
import gobject
import gtk
import datetime
import ConfigParser
import blipy
import re
import threading
import time
import webkitgtk
import xml.sax.saxutils

SETTINGS_FILE = '~/.blipoc/settings.cfg'

class AdiumTheme(object):
	def read_resource(self, resource_dir, res_name):
		return open(os.path.join(resource_dir, res_name), 'rb').read()

	def __init__(self, style_dir):
		resource_dir = os.path.join(style_dir, 'Contents', 'Resources')
		self.css = self.read_resource(resource_dir, 'main.css')
		self.header = self.read_resource(resource_dir, 'Header.html')
		self.footer = self.read_resource(resource_dir, 'Footer.html')
		self.out_content = self.read_resource(resource_dir, os.path.join('Outgoing', 'Content.html'))
		self.out_next_content = self.read_resource(resource_dir, os.path.join('Outgoing', 'NextContent.html'))
		self.in_content = self.read_resource(resource_dir, os.path.join('Incoming', 'Content.html'))
		self.in_next_content = self.read_resource(resource_dir, os.path.join('Incoming', 'NextContent.html'))
		self.status = self.read_resource(resource_dir, 'Status.html')
		self.variant = 'Variants/Red - Green.css'
		self.load_template(style_dir)

	def load_template(self, style_dir):
		self.path = os.path.abspath(os.path.join(style_dir, 'Contents', 'Resources', 'Template.html'))
		template = self.read_resource('.', 'Template.html')
		parts = template.split('%@')
		self.template = parts[0] + self.path + parts[1] + self.css + parts[2] + self.variant + parts[3] + self.header + parts[4] + self.footer + parts[5]

	def format_date(self, matchobj):
		return self.time.strftime(str(matchobj.group('fmt')))

	def replace_tokens(self, template, values):
		for key, value in values.iteritems():
			if type(value) is datetime.datetime:
				value = value.strftime('%H:%M:%S')
			template = template.replace('%%%s%%' % key, value)
		if values.has_key('time'):
			self.time = values['time']
			template = re.sub(r'%time\{(?P<fmt>[^}]*)\}%', self.format_date, template)
		return template

class BlipChat(gtk.Window):
	incoming = None
	last_title = None
	last_seen = None
	timer = None
	refresh_flag = threading.Event()

	def __init__(self, theme):
		self.config = ConfigParser.ConfigParser()
		self.config.read(os.path.expanduser(SETTINGS_FILE))
		username, password = self.config.get('user', 'username'), self.config.get('user', 'password')
		self.account = blipy.Account()
		self.account.set_credentials(username, password)
		self.user = username

		self.theme = theme
		gtk.Window.__init__(self)
		self._loading = False
		self._browser= webkitgtk.WebView()
		self._browser.connect('load-finished', self._onload)

		self._scrolled_window = gtk.ScrolledWindow()
		self._scrolled_window.props.hscrollbar_policy = gtk.POLICY_AUTOMATIC
		self._scrolled_window.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC
		self._scrolled_window.add(self._browser)
		self._scrolled_window.show_all()

		self._entry = gtk.Entry()
		self._entry.connect('activate', self.send)

		self._vbox = gtk.VBox(spacing = 6)

		self._vbox.pack_start(self._scrolled_window)
		self._vbox.pack_end(self._entry, expand = False)
		self.add(self._vbox)
		self.set_border_width(6)
		self.set_title('Blip')

		self.set_default_size(600, 480)
		self.connect('destroy', self._onquit)

		self._browser.load_string(self.theme.template, "text/html", "utf-8", self.theme.path)

		self._entry.grab_focus()
		self.show_all()

	def send(self, entry):
		blipy.Update.create(self.account, entry.props.text)
		entry.props.text = u''
		self.refresh()

	def do_updates(self):
		while self.running:
			msgs = blipy.Update.dashboard(self.account, self.last_seen)
			if msgs:
				last = msgs[0]
				msgs.reverse()
				for msg in msgs:
					gtk.gdk.threads_enter()
					self.append(msg)
					gtk.gdk.threads_leave()
				self.last_seen = last.id
			self.refresh_flag.wait(timeout = 5)
			self.refresh_flag.clear()

	def refresh(self):
		self.refresh_flag.set()

	def _onload(self, page, frame):
		self.running = True
		self.updater = threading.Thread(target = self.do_updates)
		self.updater.start()

	def _onquit(self, window):
		self.running = False
		self.updater.join()
		gtk.main_quit()

	def append(self, message):
		incoming = message.user.login != self.user
		fun = 'appendNextMessage'
		tpl = self.theme.in_next_content if incoming else self.theme.out_next_content
		title = '%s → %s' % (message.user.login, message.recipient.login) if message.recipient else message.user.login
		if self.incoming != incoming or title != self.last_title:
			fun = 'appendMessage'
			tpl = self.theme.in_content if incoming else self.theme.out_content
			self.incoming = incoming
			self.last_title = title
		body = xml.sax.saxutils.escape(message.body)
		for pic in message.pictures:
			body += '<br /><img src="%s" style="height: 100px" alt="pic" />' % pic.url
		text = self.theme.replace_tokens(tpl, {
				'message': body,
				'sender': title,
				'userIconPath': 'http://blip.pl/' + message.user.avatar.url_90,
				'time': message.created_at
			})
		text = '\\n'.join(text.replace('\\', '\\\\').replace('"', '\\"').split('\n'))
		script = "%s(\"%s\")" % (fun, text)
		self._browser.execute_script(script)

if __name__ == "__main__":
	window = BlipChat(AdiumTheme('Stockholm.AdiumMessageStyle'))
	gtk.gdk.threads_init()
	gtk.main()

